#include "rudp.h"
#include <stdio.h>
#include <stdint.h>

#include <unistd.h>  
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <pthread.h>  
#include <netinet/in.h>  
#include <errno.h>  
#include <fcntl.h>

#include <sys/time.h>  
#include <arpa/inet.h>  
#include <sys/socket.h>  
#include <sys/select.h>  

static void
dump_recv(struct rudp *U) {
	char tmp[MAX_PACKAGE];
	int n;
	while ((n = rudp_recv(U, tmp))) {
		if (n < 0) {
			printf("CORRPUT\n");
			break;
		}
		int i;
		printf("RECV ");
		for (i=0;i<n;i++) {
			printf("%c ", (uint8_t)tmp[i]);
		}
		printf("\n");
	}
}

static void
pack_send(struct rudp_package *p, int sock, struct sockaddr * addr) {
	static int idx = 0;
	printf("send %d : ", idx++);
	while (p) {
		printf("(");

		int i;
		for (i=0;i<p->sz;i++) {
			printf("%02x ", (uint8_t)p->buffer[i]);
		}

		if (idx !=11) 
			sendto(sock, p->buffer, p->sz,0, addr, sizeof(*addr));  
		else
			printf("drop %d",idx);

		printf(") ");
		p=p->next;
	}
	printf("\n");
}


static void udp_noblock(int sock)
{
	int flags = 0;
	flags = fcntl(sock, F_GETFL, 0); 
	fcntl(sock, F_SETFL, flags | O_NONBLOCK);
}

static int udp_select(int sock, int timeoutsec)
{
	struct timeval timeout;    // 定时变量
	fd_set rset;//创建文件描述符的聚合变量
	int ret = 0;  
    FD_ZERO(&rset);  
    FD_SET(sock, &rset);  

    timeout.tv_sec = timeoutsec;   
    timeout.tv_usec = 0;  

    ret = select(sock + 1, &rset, NULL, NULL, &timeout);
    if (ret == 0){
    	return 0;
    }

    if (ret > 0){
    	if (FD_ISSET(sock, &rset)){
    		return 1;
    	}
    }
    return -1;
}


static void
update_send_and_recv(struct rudp *U, int sock,int tick) {
	char message[512];
	int recv_ret = 0;
	int select_ret = 0;
	struct rudp_package *send = NULL;
    
    static struct sockaddr addr;
    static int    addr_len = sizeof(addr);
    static int    have_recv = 0;

	select_ret  = udp_select(sock, 1);
    
    printf("select ret %d\n", select_ret);

	if (select_ret > 0){

		recv_ret  = recvfrom(sock, message, sizeof(message), 0, &addr, (socklen_t*)&addr_len);  

		printf("recv ret %d \n", recv_ret);

		if (recv_ret > 0){
			have_recv++;
			send = rudp_update(U, message, recv_ret, tick);
		}

	}else{
		send = rudp_update(U, NULL, 0, tick);
	}

	if (send && have_recv > 0)
		pack_send(send, sock, &addr);
}


int port=6770;  
  
int main(int argc, char** argv) {  
   
    int socket_descriptor;  
    struct sockaddr_in sin;  

	struct rudp *U = rudp_new(1, 5);
    
    printf("Waiting for data form sender \n");  

    bzero(&sin,sizeof(sin));  

    sin.sin_family=AF_INET;  
    sin.sin_addr.s_addr=htonl(INADDR_ANY);  
    sin.sin_port=htons(port);  
  
    socket_descriptor = socket(AF_INET,SOCK_DGRAM,0);  

    udp_noblock(socket_descriptor);

    bind(socket_descriptor,(struct sockaddr *)&sin,sizeof(sin));  
  
  	uint index = 0;
    
    char buffer[128];

    while(1)  
    {  
    	index++;

		update_send_and_recv(U, socket_descriptor, 1);

		dump_recv(U);

		sprint(buffer, "123 %d", index);

		rudp_send(U, buffer, strlen(buffer));
		
		printf("index = %d \n", index);

    }
      
  
    close(socket_descriptor);  

    exit(0);  
  
    return (EXIT_SUCCESS);  
}  
